package cn.lixin.hrm.controller;

import cn.lixin.hrm.doc.CourseDoc;
import cn.lixin.hrm.mapper.HighlightResultMapper;
import cn.lixin.hrm.query.CourseDocQuery;
import cn.lixin.hrm.query.PageList;
import cn.lixin.hrm.repository.CourseDocRepository;
import cn.lixin.hrm.util.AjaxResult;
import cn.lixin.hrm.vo.AggVo;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * ES的服务-- 将doc保存到ES中
 *      ES如何保存数据
 *      -- 查询删除添加，需要注入courseDocRepository
 *      --并且 CourseDocRepository需要继承ElasticsearchRepository
 */
@RestController
@RequestMapping("/courseDoc")
public class CourseDocController {
    @Autowired
    private CourseDocRepository courseDocRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    //注入高亮结果映射器
    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @PostMapping("/addCourseDoc")
    @PreAuthorize("hasAnyAuthority('courseDoc:add')")
    public AjaxResult addCourseDoc(@RequestBody CourseDoc courseDoc){
        courseDocRepository.save(courseDoc);
        return AjaxResult.me();
    }
    @PostMapping("/delCourseDoc/{id}")
    @PreAuthorize("hasAnyAuthority('courseDoc:delete')")
    public AjaxResult delCourseDoc(@PathVariable Long id){
        courseDocRepository.deleteById(id);
        return AjaxResult.me();
    }


    @PostMapping("/searchQuery")
    public AjaxResult searchQuery(@RequestBody CourseDocQuery docQuery){
        //创建NativeQueryBuilder
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //添加聚合查询
        builder.addAggregation(AggregationBuilders.terms("tenantNameAgg").field("tenantName").order(Terms.Order.count(false)).size(20));
        builder.addAggregation(AggregationBuilders.terms("couseTypeAgg").field("courseTypeName").order(Terms.Order.count(false)).size(20));
        //指定高亮的字段
        HighlightBuilder.Field hfield = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
        builder.withHighlightFields(hfield);
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //高级查询
        String keyword = docQuery.getKeyword();
        if(StringUtils.isNotBlank(keyword)){
            //支持多个字段的匹配
            boolQuery.must(QueryBuilders.multiMatchQuery(keyword,"name","courseTypeName"));
        }
        //过滤
        Float priceMax = docQuery.getPriceMax();
        if(priceMax != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(priceMax));
        }

        Float priceMin= docQuery.getPriceMin();
        if(priceMin != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(priceMin));
        }
        builder.withQuery(boolQuery);

        //排序--获取排序的类型
        String sortType = docQuery.getSortType();
        SortOrder order = sortType.equals(SortOrder.DESC.toString())?SortOrder.DESC:SortOrder.ASC;
        //判断是否有排序字段 如果没有  默认 以价格排序
        String field = docQuery.getSortField();
        field = StringUtils.isNotBlank(field)?field:"price";
        builder.withSort(new FieldSortBuilder(field).order(order));
        //分页
        builder.withPageable(PageRequest.of(docQuery.getPage()-1,docQuery.getRows() ));

        //Page<CourseDoc> docs = courseDocRepository.search(builder.build());
        AggregatedPage<CourseDoc> docs = elasticsearchTemplate.queryForPage(builder.build(), CourseDoc.class, highlightResultMapper);
        //获取聚合查询的结果
        StringTerms tenantTerms = (StringTerms) docs.getAggregation("tenantNameAgg");
        //创建集合 用来封装机构名称聚合的结果
        List<AggVo> tenantList = new ArrayList<>();
        List<StringTerms.Bucket> buckets = tenantTerms.getBuckets();
        buckets.stream().forEach(bucket -> {
            //创建Aggvo对象
            AggVo aggVo = new AggVo();
            aggVo.setName(bucket.getKeyAsString());
            aggVo.setCount(bucket.getDocCount());
            tenantList.add(aggVo);
        });
        StringTerms typeTerms = (StringTerms) docs.getAggregation("couseTypeAgg");
        //创建集合 用来封装机构名称聚合的结果
        List<AggVo> typeList = new ArrayList<>();
        List<StringTerms.Bucket> typeBuckets = typeTerms.getBuckets();
        typeBuckets.stream().forEach(bucket -> {
            //创建Aggvo对象
            AggVo aggVo = new AggVo();
            aggVo.setName(bucket.getKeyAsString());
            aggVo.setCount(bucket.getDocCount());
            typeList.add(aggVo);
        });
        //创建一个hashmap封装聚合所有的结果
        HashMap<String, List<AggVo>> hashMap = new HashMap<>();
        hashMap.put("tenantList", tenantList);
        hashMap.put("typeList", typeList);

        //准备封装数据的分页对象
        PageList<CourseDoc> pageList = new PageList<>();
        pageList.setRows(docs.getContent());
        pageList.setTotal(docs.getTotalElements());
        pageList.setHashMap(hashMap);
        return AjaxResult.me().setResultObj(pageList);
    }


}
